/*
 * Group 3, User Interface Programming II (vt11)
 * Pooya | Flora | Monica | Can
 */
package vical.view;

import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;

/**
 * The Layout Manager to place information, 
 * looks like many fixed bars and one expendable panel at bottom
 * 
 * @author Can
 */
public class InfoLayout implements LayoutManager2 {

    private final int defaultWidth = 450;
    private final int defaultHeight = 400;
    private static final String MESSAGE = "Message";
    private static final String FIXED = "Bar";
    private static final String FLEXIBLE = "Flexible";
    private Container target;
    private ArrayList<Component> fixedComponents;
    private Component messageComponent;
    private Component flexibleComponent;
    private LayoutManager mainLayout;
    private LayoutManager fixedPanelLayout;
    private LayoutManager flexiblePanelLayout;
    private LayoutManager messagePanelLayout;
    private JPanel flexibleComponentPanel;
    private JPanel fixedComponentsPanel;
    private JPanel messagePanel;

    public InfoLayout(Container target) {
        this.target = target;
        this.fixedComponents = new ArrayList<Component>();

        // new panels
        fixedComponentsPanel = new JPanel();
        flexibleComponentPanel = new JPanel();
        messagePanel = new JPanel();
        // new layouts
        mainLayout = new BorderLayout();
        fixedPanelLayout = new BoxLayout(fixedComponentsPanel, BoxLayout.Y_AXIS);
        flexiblePanelLayout = new BorderLayout();
        messagePanelLayout = new BorderLayout();
        // set layouts
        fixedComponentsPanel.setLayout(fixedPanelLayout);
        flexibleComponentPanel.setLayout(flexiblePanelLayout);
        messagePanel.setLayout(messagePanelLayout);
        // main layout
        this.target.setLayout(mainLayout);
        this.target.add(fixedComponentsPanel, BorderLayout.NORTH);
        this.target.add(flexibleComponentPanel, BorderLayout.CENTER);
        this.target.add(messagePanel, BorderLayout.SOUTH);
    }

    private void refreshLayout() {
        messagePanel.removeAll();
        if (this.messageComponent != null) {
            messagePanel.add(messageComponent, BorderLayout.CENTER);
        }
        flexibleComponentPanel.removeAll();
        if (this.flexibleComponent != null) {
            flexibleComponentPanel.add(flexibleComponent, BorderLayout.CENTER);
        }
        fixedComponentsPanel.removeAll();
        for (Component component : fixedComponents) {
            JPanel tempPanel = new JPanel(new BorderLayout());
            tempPanel.add(component);
            fixedComponentsPanel.add(tempPanel);
        }
    }

    public void addLayoutComponent(String name, Component comp) {
        if (name == null || name.equals(FIXED)) {
            this.fixedComponents.add(comp);
            JPanel tempPanel = new JPanel(new BorderLayout());
            tempPanel.add(comp);
            fixedComponentsPanel.add(tempPanel);
        } else if (name.equals(MESSAGE)) {
            this.messageComponent = comp;
            this.messagePanel.add(comp, BorderLayout.CENTER);
        } else if (name.equals(FLEXIBLE)) {
            this.flexibleComponent = comp;
            this.flexibleComponentPanel.add(comp, BorderLayout.CENTER);
        } else {
            throw new IllegalArgumentException("cannot add to layout: Invalid paramerters");
        }
    }

    public void addLayoutComponent(Component comp, Object constraints) {
        if (constraints == null || constraints instanceof String) {
            addLayoutComponent((String) constraints, comp);
        } else {
            throw new IllegalArgumentException("cannot add to layout: constraint must be a string (or null)");
        }
    }

    public void removeLayoutComponent(Component comp) {
        if (comp == this.messageComponent) {
            this.messageComponent = null;
            this.messagePanel.remove(comp);
        } else if (comp == this.flexibleComponent) {
            this.flexibleComponent = null;
            this.flexibleComponentPanel.remove(comp);
        } else {
            this.fixedComponents.remove(comp);
            this.fixedComponentsPanel.remove(comp);
        }
    }

    public Dimension preferredLayoutSize(Container target) {
        checkContainer(target);
        return new Dimension(defaultWidth, defaultHeight);
    }

    public Dimension minimumLayoutSize(Container target) {
        checkContainer(target);
        return new Dimension(defaultWidth, defaultHeight);
    }

    public void layoutContainer(Container target) {
        synchronized (this) {
            checkContainer(target);
            mainLayout.layoutContainer(target);
        }
    }

    public Dimension maximumLayoutSize(Container target) {
        return new Dimension(defaultWidth, defaultHeight);
    }

    public float getLayoutAlignmentX(Container target) {
        return 10f;
    }

    public float getLayoutAlignmentY(Container target) {
        return 10f;
    }

    public void invalidateLayout(Container target) {
        checkContainer(target);
    }

    private void checkContainer(Container target) {
        if (this.target != target) {
            throw new AWTError("InfoLayout can't be shared");
        }
    }

    // for testing
    public static void main(String[] args) {

        JFrame frame = new JFrame();
        frame.getContentPane().setLayout(new InfoLayout(frame.getContentPane()));
        frame.getContentPane().add(new JButton("This is a test!"));
        frame.getContentPane().add(new JButton("This is a test!"));
        frame.getContentPane().add(new JButton("This is a test!"));
        frame.getContentPane().add(new JButton("This is a test!"));
        frame.getContentPane().add(new JButton("This is a test!"));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setPreferredSize(new Dimension(300, 500));
        frame.setVisible(true);
    }
}
